﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace Visualizator.Physics
{
    /// <summary>
    /// Representacion del sistema masa-resorte, usando una representacion
    /// de datos ajustada al modelo de integarcion Verlet, es decir, en vez
    /// de almacenar la velocidad actual de una particula, almacenamos su
    /// posicion anterior, de donde sacamos la velocidad.
    /// 
    /// Vamos a necesitar 3 algoritmos.
    /// 1. Acumulacion de fuerzas 
    ///   -> F = m * A.
    ///   -> Aplicar gravedad.
    /// 2. Integracion Verlet (utilizanado: pos, prevPos)
    ///   -> X = 2X - X' + A * T^2
    /// 3. Satisfaccion de resortes (utilizando: pos, mass, springIndex1/2, restLength, k)
    ///   -> F = -k * X
    /// 4. [Opcional] Angular springs?
    /// </summary>
    public class MassSpringSystem2
    {
        public Vector3 Gravity;

        // Posiciones actuales
        public Vector3[] Pos;

        // Posiciones anteriores.
        public Vector3[] PrevPos;

        // Fuerzas acumuladas.
        public Vector3[] Force;


        /// <summary>
        /// Mas comodo que accesar los float[] directamente.
        /// </summary>
        public void SetPos(int index, Vector3 value)
        {
            Pos[index] = value;
        }

        /// <summary>
        /// Mas comodo que accesar los float[] directamente.
        /// </summary>
        public Vector3 GetPos(int index)
        {
            return Pos[index];
        }

        /// <summary>
        /// Mas comodo que accesar los float[] directamente.
        /// </summary>
        public void SetPrevPos(int index, Vector3 value)
        {
            PrevPos[index] = value;
        }

        /// <summary>
        /// Mas comodo que accesar los float[] directamente.
        /// TODO: Deberia ser ApplyImpulse?
        /// </summary>
        public void SetForce(int index, Vector3 value)
        {
            Force[index] = value;
        }

        /// <summary>
        /// La masa de cada punto.
        /// TODO: Sera mejor guardar el inverso de la masa?
        /// </summary>
        public float[] Mass;

        /// <summary>
        /// Inicializa la estructura de datos para almacenar el sistema.
        /// </summary>
        public MassSpringSystem2(int particleCount, int springCount)
        {
            Pos = new Vector3[particleCount];

            PrevPos = new Vector3[particleCount];

            Force = new Vector3[particleCount];

            Mass = new float[particleCount];

            SpringIndex1 = new int[springCount];
            SpringIndex2 = new int[springCount];
            RestLength = new float[springCount];
            K = new float[springCount];
        }


        /// <summary>
        /// El indice 1 de los resortes.
        /// </summary>
        public int[] SpringIndex1;

        /// <summary>
        /// El indice 2 de los resortes.
        /// </summary>
        public int[] SpringIndex2;

        /// <summary>
        /// Longitud de descanso del resorte.
        /// </summary>
        public float[] RestLength;

        /// <summary>
        /// Constantes de elasticidad de cada resorte.
        /// </summary>
        public float[] K;

    }
}
